www.gusucode.com > XbPhp开发框架 v1.4.5PHP源码程序 > XbPhp开发框架 v1.4.5/xbphp/xbphp/XbPhp/view/view.php
<?php /** * 视图 * @author wave */ class view { //左边界符号 public $left_delimiter = LDELIMITER; //右边界符号 public $right_delimiter = RDELIMITER; //定义模版的后缀 public $suffix = SUFFIX; //用来保存变量 public $_value = array(); //获取编译消耗时间 public $compile_time = null; //要替换的符号 protected $replaced = array( 'sign'=>array('[',']','.',"'",'"'), 'foreach'=>array('as','=>') ); public function __construct() { //定义根目录 $this->root = ROOT.DS.APP_PATH.DS; //判断是否开启smarty if(SMARTY == 1) { $this->_get_smarty(); } } /** * 设置键值 * @param string $key 键 * @param string $value 值 */ public function __set($key,$value) { $this->{$key} = $value; } /** * 毁消变量 * @param string $key 键 * @author wave */ public function __unset($key) { unset($this->{$key}); } /** * 赋值变量 * @param String $key 定义模版变量 * @param String $value 要赋值给模版的变量 * @author wave */ public function assign($key,$val) { if(isset($key) && !empty($key) && !empty($val)) { $this->_value[$key] = $val; } } /** * 渲染模版 * @param Array $array 自定义模版变量 * @param string $templateFile 模版路径 * @author wave */ public function render($array = array(),$templateFile = null) { $tmpfile = !empty($templateFile) ? $templateFile : $this->_get_action(); //模版文件路径 $file_path = $this->root.ROOT_VIEW.DS.$tmpfile.$this->suffix; if(strpos($tmpfile, '.') !== false) { $file_path = $this->root.ROOT_VIEW.DS.$tmpfile; } if(!file_exists($file_path)) { load('404.tpl',ROOT_PATH.DS.ROOT_ERROR.DS.'tpl'); exit; } extract($array); require $file_path; } /** * layout渲染模版 * @param Array $array 自定义模版变量 * @param string $templateFile 模版路径 * @author wave */ public function renderLayout($array = array(),$templateFile = null) { extract($array); $file_path = $this->root.DS.'layout'.DS."index.php"; require $file_path; } /** * 引入模版返回代碼 * @param Array $array 自定义模版变量 * @param string $templateFile 模版路径 * @return HTML * @author wave */ public function renderHtml($array = array(),$templateFile = null) { ob_start(); $this->render($array,$templateFile); $content = ob_get_contents(); ob_clean(); return $content; } /** * 引入模版 * @param String $templateFile 定义模版路径 * @author wave */ public function display($templateFile = null) { $start_time = microtime(true); //获取开始时间 $path = $this->_compresFile($templateFile); require $path; $end_time = microtime(true); //获取结束时间 $this->compile_time = ' (display方法消耗了'.sprintf('%0.4f',($end_time - $start_time)).'秒)'; } /** * 编译文件 * @param string $templateFile 文件名 * @return string * @author wave */ private function _compresFile($templateFile = null) { $tmpfile = !empty($templateFile) ? $templateFile : $this->_get_action(); //编译文件路径 $tmp_path = $this->root.CACHE.DS.TEMPLATES; $file_path = $this->root.ROOT_VIEW.DS.$tmpfile.$this->suffix; //定义了文件路径 if(strpos($templateFile, '.') !== false) { //模版文件路径 $file_path = $this->root.ROOT_VIEW.DS.$tmpfile; } if(file_exists($templateFile)) { $file_path = $templateFile; } $tmp_name = 'xb_'.md5($tmpfile).'.php'; if(!file_exists($file_path)) { load('404.tpl',ROOT_PATH.DS.ROOT_ERROR.DS.'tpl'); exit; } if(!file_exists($tmp_path)) { mkdirs(DS.CACHE.DS.TEMPLATES); } $file_path_time = filemtime($file_path); $tmp_path_time = 0; //判断缓存文件是否存在 if(file_exists($tmp_path.DS.$tmp_name)) { $tmp_path_time = filemtime($tmp_path.DS.$tmp_name); } //判断编译文件是否存在,或者模版文件修改时间小于编译文件修改的时间 if(!is_file($tmp_path.DS.$tmp_name) || ($file_path_time > $tmp_path_time)) { $html = file_get_contents($file_path); $html = $this->_include($html); $html = $this->_if($html); $html = $this->_foreach($html); $html = $this->_echo($html); $html = (COMPRESS == 1) ? $this->compress_html($html) : $html; file_put_contents($tmp_path.DS.$tmp_name,$html); } return $tmp_path.DS.$tmp_name; } /** * 替换输出 * 例子<{$a}> * @param string $html 要替换的HTML * @return resource * @author wave */ private function _echo($html) { $replaced = '/'.$this->left_delimiter.'\$(.*?)'.$this->right_delimiter.'/is'; if(preg_match_all($replaced,$html,$garr,PREG_SET_ORDER)) { foreach($garr as $key => $val) { if(isset($val['1'])) { $val['1'] = str_replace($this->replaced['sign'],' ', $val['1']); $v_arr = array_values(array_filter(explode(' ', $val['1']))); $_str = null; foreach($v_arr as $k => $v) { if($k == 0) { $_str .= '$this->_value["'.$v.'"]'; }else{ $_str .= '["'.$v.'"]'; } } $_str = '<?php echo '.$_str.'; ?>'; $html = str_replace($val['0'],$_str,$html); } } } return $html; } /** * 替换引入函数 * 例子<{include file="路径加文件"}> 注意:路径带有模版变量则不编译该文件 * @param String $html 要替换的HTML * @return HTML * @author wave */ private function _include($html) { //正则替换include函数 $preg_include = '/'.$this->left_delimiter.'include\s+file=\"(.*?)\"'.$this->right_delimiter.'/is'; if(preg_match_all($preg_include,$html,$arr,PREG_SET_ORDER)) { foreach($arr as $key => $val) { $blooen = 0; //判断是否有加入模版变量 $_str = ''; //要保存的字符串 $val['1'] = $this->_replace_arr( array($this->left_delimiter,$this->right_delimiter), ' ', $val['1'] ); foreach($val['1'] as $v) { $_val = ''; if(strpos($v,'$')!== false) { $blooen = 1; if(strpos($v,'[') !==false) { $_val = substr($v,strpos($v,'$')+strlen('$'),strpos($v,'$')+strpos($v,'[')-strlen('[')); $_str .= '$this->_value["'.$_val.'"]'; $_val = substr($v,strpos($v,'$')+strpos($v,'[')); $_str .= $_val."."; }else { $_val = substr($v,strpos($v,'$')+strlen('$')); $_str .= '$this->_value["'.$_val.'"].'; } }else { $_str .= '"'.$v.'".'; } } if(empty($blooen)) { //没有模版变量 $path_str = str_replace('\\','/',$this->_compresFile(str_replace(array('"',"'"),'',rtrim($_str,'.')))); $_str = '<?php include "'.$path_str.'"; ?>'; $html = str_replace($val['0'],$_str,$html); }else { //引入的模版变量 $_str = '<?php include '.rtrim($_str,'.').'; ?>'; $html = str_replace($val['0'],$_str,$html); } } } return $html; } /** * 模版标签forach[支持嵌套,与smarty写法差多] * <{foreach $list as $k=>$v}><{$k}>---<{$v}><{/foreach}> * @param string $html 要替换的HTML的代码 * @return HTML * @author wave */ private function _foreach($html) { $preg = '/'.$this->left_delimiter.'foreach (.*?)'.$this->right_delimiter.'/is'; if(preg_match_all($preg,$html,$arr,PREG_SET_ORDER)) { foreach($arr as $key => $val) { $_str = ''; $val['1'] = $this->_replace_arr(array('as','=>'),' ',$val['1']); if(is_array($val['1'])) { foreach($val['1'] as $k => $v) { $_val = ''; if($k == 0) { if(strpos($v,'$')!== false) { if(strpos($v,'[') !==false) { $_val = substr($v,strpos($v,'$')+strlen('$'),strpos($v,'$')+strpos($v,'[')-strlen('[')); $_str .= '$this->_value["'.$_val.'"]'; $_val = substr($v,strpos($v,'$')+strpos($v,'[')); $_str .= $_val.""; }else { $_val = substr($v,strpos($v,'$')+strlen('$')); $_str .= '$this->_value["'.$_val.'"]'; } $_str .= ' as '; } }else { $_val = substr($v,strpos($v,'$')+strlen('$')); $_str .= '$this->_value["'.$_val.'"]'; $_str .= ' => '; } } $_str ='<?php foreach( '.rtrim($_str,' => ').' ) { ?>'; $html = str_replace($val['0'],$_str,$html); $html = str_replace('<{/foreach}>','<?php } ?>',$html); } } } return $html; } /** * 替换IF语句[支持嵌套] * 例子<{if $a == $b }>123<{else}>2323<{/if}> * @param string $html 值 * @return HTML * @return wave */ private function _if($html) { $preg = '/'.$this->left_delimiter.'if\s+(.*?)\s*'.$this->right_delimiter.'(.*?)'.$this->left_delimiter.'\/if'.$this->right_delimiter.'/s'; if(preg_match_all($preg,$html,$garr,PREG_SET_ORDER)) { $replace = array('=','>','<','!','|','&'); foreach($garr as $value) { $rarr = $value['1']; $value['1'] = $this->_replace_arr($replace,' ',$value['1'],' '); foreach($value['1'] as $v) { if(strpos($rarr,$v) !== false) { $rarr = substr_replace($rarr,'',strpos($rarr,$v),strlen($v)); } } $rarr = $this->_replace_arr('','',$rarr,' '); $conditions = null; foreach($value['1'] as $key => $val) { //进行遍历拼接 $left_bracket = null; //左边括号 $right_bracket = null; //右边括号 if(strpos($val,'(') !== false) { //判断是否写了左边括号 $left_bracket = '('; } if(strpos($val,')') !== false) { //判断是否写了右边括号 $right_bracket = ')'; } if(strpos($val,'$') !== false) { $str = substr($val,1); $v_arr = $this->_replace_arr($this->replaced['sign'],' ',$str,' '); $_str = null; foreach($v_arr as $k => $v) { if($k == 0) { $_str .= '$this->_value["'.$v.'"]'; }else{ $_str .= '["'.$v.'"]'; } } $val = str_replace($val,$left_bracket.$_str.$right_bracket,$val); } $conditions .= $val.' '; if(isset($rarr[$key])) { $conditions.= $rarr[$key].' '; } } $value['2'] = str_replace($this->left_delimiter.'else'.$this->right_delimiter,'<?php }else { ?>',$value['2']); $if = '<?php if('.$conditions.'){?>'.$value['2'].'<?php } ?>'; $html = str_replace($value['0'],$if,$html); } $html = $this->_if($html); } return $html; } /** * 压缩html : 清除换行符,清除制表符,去掉注释标记 * @param $string * @return 压缩后的$string * */ protected function compress_html($string) { $string = str_replace("\r\n", '', $string); //清除换行符 $string = str_replace("\n", '', $string); //清除换行符 $string = str_replace("\t", '', $string); //清除制表符 $pattern = array ( "/> *([^ ]*) *</", //去掉注释标记 "/[\s]+/", "/<!--[^!]*-->/", "/\" /", "/ \"/", "'/\*[^*]*\*/'" ); $replace = array ( ">\\1<", " ", "", "\"", "\"", "" ); return preg_replace($pattern, $replace, $string); } /** * 获取smarty模版引擎 * @author wave */ private function _get_smarty() { load('Smarty.class.php','vendors/Smarty/libs'); $this->smarty = Xbphp::run_cache('Smarty'); $this->smarty->cache_dir = $this->root.CACHE.DS.TEMPLATES; $this->smarty->template_dir = $this->root.ROOT_VIEW.DS; $this->smarty->compile_dir = $this->root.CACHE.DS.TMP; $this->smarty->left_delimiter = $this->left_delimiter; $this->smarty->right_delimiter = $this->right_delimiter; } /** * 替换截取字符 * @param Array or String $replaced 要替换的 * @param Array or String $replace 被替换的 * @param String $str 查找字符串 * @param String $explode 截取的字符串 * @return Array * @author wave */ private function _replace_arr($replaced,$replace,$str,$explode =' ') { if(!empty($replaced) && !empty($replace)) { $str = str_replace($replaced, $replace, $str); } $arr = array_filter(explode($explode, $str)); $arr = array_values($arr); return $arr; } /** * 获取当前访问的方法 * @return String * @author wave */ private function _get_action() { $arr = Xbphp::getServerUrl(); if(!isset($arr['0'])) { $arr['0'] = M_INDEX; } if(!isset($arr['1'])) { $arr['1'] = A_INDEX; } if(isset($_GET[M]) && !empty($_GET[M])) { $arr['0'] = $_GET[M]; } if(isset($_GET[A]) && !empty($_GET[A])) { $arr['1'] = $_GET[A]; } return $arr['0'].DS.$arr['1']; } }